package com.jijunpeng.javafx.cipher.controller.api;

import cn.hutool.crypto.GlobalBouncyCastleProvider;
import com.jijunpeng.javafx.cipher.common.LetterCaseEnum;
import com.jijunpeng.javafx.cipher.common.enums.CharsetEnum;
import com.jijunpeng.javafx.cipher.common.enums.CipherProviderEnum;
import com.jijunpeng.javafx.cipher.exception.InputTypeException;
import com.jijunpeng.javafx.cipher.exception.OutputTypeException;
import javafx.collections.FXCollections;
import javafx.scene.control.ComboBox;
import javafx.scene.control.RadioButton;
import javafx.scene.control.TextArea;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;

import java.nio.charset.Charset;

/**
 * @author Ji Junpeng
 * @date 2019-12-01 01-11
 */
public interface ICipherController extends ILeftStringCharsetController {
    RadioButton getLeftHexRb();

    RadioButton getLeftBase64Rb();

    @Override
    RadioButton getLeftStringRb();

    RadioButton getRightHexRb();

    RadioButton getRightBase64Rb();

    @Override
    ComboBox<CharsetEnum> getLeftStringCharsetComboBox();

    TextArea getLeftTextArea();

    TextArea getRightTextArea();

    ComboBox<CipherProviderEnum> getCipherProviderComboBox();

    default ComboBox<LetterCaseEnum> getRightHexCaseComboBox() {
        return null;
    }

    default void initCipherController() {
        initLeftStringCharset();
        if (getCipherProviderComboBox() != null) {
            getCipherProviderComboBox().setItems(FXCollections.observableArrayList(CipherProviderEnum.values()));
            getCipherProviderComboBox().setValue(CipherProviderEnum.values()[0]);
            GlobalBouncyCastleProvider.setUseBouncyCastle(getCipherProviderComboBox().getValue() == CipherProviderEnum.BOUNCY_CASTLE);
            getCipherProviderComboBox().valueProperty().addListener((observable, oldValue, newValue) -> GlobalBouncyCastleProvider.setUseBouncyCastle(newValue == CipherProviderEnum.BOUNCY_CASTLE));
        }
        if (getRightHexCaseComboBox() != null) {
            getRightHexCaseComboBox().setDisable(!getRightHexRb().isSelected());
            getRightHexCaseComboBox().setItems(FXCollections.observableArrayList(LetterCaseEnum.values()));
            getRightHexCaseComboBox().setValue(LetterCaseEnum.values()[0]);
            getRightHexRb().selectedProperty().addListener((observable, oldValue, newValue) -> getRightHexCaseComboBox().setDisable(!newValue));
        }
    }

    default byte[] getLeftBytes() throws Exception {
        String inputStr = getLeftTextArea().getText();
        byte[] resultBytes;
        if (getLeftHexRb().isSelected()) {
            resultBytes = Hex.decodeHex(inputStr);
        } else if (getLeftBase64Rb().isSelected()) {
            resultBytes = Base64.decodeBase64(inputStr);
        } else if (getLeftStringRb().isSelected()) {
            Charset charset = getLeftStringCharsetComboBox().getValue().getCharset();
            resultBytes = inputStr.getBytes(charset);
        } else {
            throw new InputTypeException();
        }
        return resultBytes;
    }

    default byte[] getRightBytes() throws Exception {
        String inputStr = getRightTextArea().getText();
        byte[] resultBytes;
        if (getRightHexRb().isSelected()) {
            resultBytes = Hex.decodeHex(inputStr);
        } else if (getRightBase64Rb().isSelected()) {
            resultBytes = Base64.decodeBase64(inputStr);
        } else {
            throw new InputTypeException();
        }
        return resultBytes;
    }

    default String buildLeftStr(byte[] outputBytes) throws Exception {
        String resultStr;
        if (getLeftHexRb().isSelected()) {
            resultStr = Hex.encodeHexString(outputBytes);
        } else if (getLeftBase64Rb().isSelected()) {
            resultStr = Base64.encodeBase64String(outputBytes);
        } else if (getLeftStringRb().isSelected()) {
            Charset charset = getLeftStringCharsetComboBox().getValue().getCharset();
            resultStr = new String(outputBytes, charset);
        } else {
            throw new OutputTypeException();
        }
        return resultStr;
    }

    default String buildRightStr(byte[] outputBytes) throws Exception {
        String resultStr;
        if (getRightHexRb().isSelected()) {
            resultStr = Hex.encodeHexString(outputBytes);
            if (getRightHexCaseComboBox() != null && getRightHexCaseComboBox().getValue() == LetterCaseEnum.UPPER) {
                resultStr = resultStr.toUpperCase();
            }
        } else if (getRightBase64Rb().isSelected()) {
            resultStr = Base64.encodeBase64String(outputBytes);
        } else {
            throw new OutputTypeException();
        }
        return resultStr;
    }
}
